﻿using AForge.Video.DirectShow;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace VCMW
{
    public partial class FrmFaceEmotion : Form
    {
        public FrmFaceEmotion()
        {
            InitializeComponent();
        }

        #region 页面公共变量
        //是否调试模式
        bool debug = false;
        int tempi = 0;//保存上一次红块数量
        int tempj = 0;//保存本次的红块数量
        System.Windows.Forms.PictureBox[] picture = new System.Windows.Forms.PictureBox[65];
        string temppath = "";
        //获取项目的根目录
        String path = Directory.GetCurrentDirectory();
        int x = 0; int y = 0; int width = 0; int height = 0;

        Logs log = new Logs();
        Debug debugFrm = new Debug();
        Helper help = new Helper();//助手类
        private FilterInfoCollection videoDevices;//调取摄像头

        #endregion

        #region 加载事件
        //加载
        private void FrmFaceEmotion_Load(object sender, EventArgs e)
        {
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            //设置窗口边框
            this.ControlBox = false;
            this.FormBorderStyle = FormBorderStyle.None;

            #region 收集页面所有PictureBox
            picture[0] = jk01;
            picture[1] = jk02;
            picture[2] = jk03;
            picture[3] = jk04;
            picture[4] = jk05;
            picture[5] = jk06;
            picture[6] = jk07;
            picture[7] = jk08;
            picture[8] = jk09;
            picture[9] = jk10;

            picture[10] = sb01;
            picture[11] = sb02;
            picture[12] = sb03;
            picture[13] = sb04;
            picture[14] = sb05;
            picture[15] = sb06;
            picture[16] = sb07;
            picture[17] = sb08;
            picture[18] = sb09;
            picture[19] = sb10;

            picture[20] = qcd01;
            picture[21] = qcd02;
            picture[22] = qcd03;
            picture[23] = qcd04;
            picture[24] = qcd05;
            picture[25] = qcd06;
            picture[26] = qcd07;
            picture[27] = qcd08;
            picture[28] = qcd09;
            picture[29] = qcd10;

            picture[30] = hyq01;
            picture[31] = hyq02;
            picture[32] = hyq03;
            picture[33] = hyq04;
            picture[34] = hyq05;
            picture[35] = hyq06;
            picture[36] = hyq07;
            picture[37] = hyq08;
            picture[38] = hyq09;
            picture[39] = hyq10;

            picture[40] = myd01;
            picture[41] = myd02;
            picture[42] = myd03;
            picture[43] = myd04;
            picture[44] = myd05;
            picture[45] = myd06;
            picture[46] = myd07;
            picture[47] = myd08;
            picture[48] = myd09;
            picture[49] = myd10;
            picture[50] = myd11;
            picture[51] = myd12;
            picture[52] = myd13;
            picture[53] = myd14;
            picture[54] = myd15;
            picture[55] = myd16;
            picture[56] = myd17;
            picture[57] = myd18;
            picture[58] = myd19;
            picture[59] = myd20;
            picture[60] = myd21;
            picture[61] = myd22;
            picture[62] = myd23;
            picture[63] = myd24;
            picture[64] = myd25;
            #endregion
            this.labtitle.Text = "";
            this.lab_xingbie.Text = "";
            this.lab_nianling.Text = "";
            this.lab_yanzhi.Text = "";
            this.lab_zuigaoyanzhi.Text = "";
            this.lab_qx_left_bottom.Text = "";
            this.lab_qx_left.Text = "";
            this.lab_qx_right.Text = "";

            this.BackColor = Color.FromArgb(24, 24, 26);//24,24,26   old:9, 9, 24
            this.aq_qingxu.BackColor = Color.FromArgb(9, 9, 24);
            //设置仪表盘色彩
            this.aq_qingxu.Range_Idx = 0;
            this.aq_qingxu.RangeColor = Color.FromArgb(68, 102, 244);
            this.aq_qingxu.Range_Idx = 1;
            this.aq_qingxu.RangeColor = Color.FromArgb(142, 68, 191);
            this.aq_qingxu.Range_Idx = 2;
            this.aq_qingxu.RangeColor = Color.FromArgb(255, 16, 110);
            string[] path_arr = path.Split('\\');
            for (int i = 0; i < path_arr.Length; i++)
            {
                if (path_arr[i].Trim().ToString() == "VCMW")
                {
                    temppath += path_arr[i];
                    break;
                }
                else
                {
                    temppath += path_arr[i] + "\\";
                }
            }
            // 枚举所有视频输入设备
            videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (videoDevices.Count == 0)
            {
                this.labtitle.Text = "未检测到摄像头！";
                return;
            }
            //打开摄像头
            help.openCan(this.videoSourcePlayer1, videoSourcePlayer1_NewFrame, videoDevices);
            if (debug)
            {
                debugFrm.Show();
            }

            //picture[0].ImageLocation = temppath + "\\Resources\\555551.png";
            //设置跨线程操作
            Control.CheckForIllegalCrossThreadCalls = false;
            foreach (var item in picture)
            {
                item.ImageLocation = temppath + "\\Resources\\77771.png";
            }
            //加载定时器
            inteverTime();
        }

        #endregion

        #region 视频流
        private void videoSourcePlayer1_NewFrame(object sender, ref Bitmap image)
        {
            Image img = System.Drawing.Image.FromFile(temppath + "\\Resources\\face.png");        //粘贴的图片
            Graphics gph = Graphics.FromImage(image);
            Pen myPen = new Pen(Color.Blue, 4);
            int left_top_x = x;
            int left_top_y = y;
            int left_bottom_x = left_top_x;
            int left_bottom_y = left_top_y + height;
            int right_top_x = left_top_x + width;
            int right_top_y = left_top_y;
            int right_bottom_x = left_bottom_x + width;
            int right_bottom_y = left_bottom_y;
            //gph.DrawEllipse(myPen, x, y, width, height);//画椭圆的方法，x坐标、y坐标、宽、高，如果是100，则半径为50
            gph.DrawImage(img, x - 100, y - 100, width + 200, height + 200);
            GC.Collect();
        }

        #endregion

        #region 定时任务
        //创建定时器
        System.Timers.Timer timer = new System.Timers.Timer();
        //定时器
        private void inteverTime()
        {
            timer.Enabled = true;
            timer.Interval = 2000;//执行间隔时间,单位为毫秒
            timer.Start();
            timer.Elapsed += new System.Timers.ElapsedEventHandler(faceRecognition);
        }

        //定时执行事件
        private void faceRecognition(object source, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                #region 识别下一个人的时候，清理上一个人的数据
                this.labtitle.Text = "";
                //this.lab_xingbie.Text = "";
                //this.lab_nianling.Text = "";
                ////this.lab_yanzhi.Text = "";
                //this.lab_zuigaoyanzhi.Text = "";
                //this.lab_qx_left_bottom.Text = "";
                //this.lab_qx_left.Text = "";
                //this.lab_qx_right.Text = "";
                //for (int i = 0; i < 40; i++)
                //{
                //    picture[i].ImageLocation = temppath + "\\Resources\\77771.png";
                //}
                //for (int i = 40; i < 55; i++)
                //{
                //    picture[i].ImageLocation = temppath + "\\Resources\\22.png";
                //}
                #endregion

                Bitmap bitmap = videoSourcePlayer1.GetCurrentVideoFrame();
                if (videoSourcePlayer1 == null || bitmap == null)
                {
                    this.labtitle.Text = "图像加载失败";
                    throw new Exception("图像加载失败！");
                }
                //调取人脸识别API，数据展示
                string url = "https://api-cn.faceplusplus.com/facepp/v3/detect";
                Dictionary<string, object> verifyPostParameters = new Dictionary<string, object>();
                //试用api_key
                //verifyPostParameters.Add("api_key", "YCtNBLKcbjWR7NUFJCgxMH9JekkBRqsa");
                //verifyPostParameters.Add("api_secret", "L4YiS_YbR93k7eifMWQQNIkEIr-15_Fn");
                verifyPostParameters.Add("api_key", "K8C6bsfZQdylnN-FVuMFr6xZ29HxQrsk");//正式
                verifyPostParameters.Add("api_secret", "P-RRNnW-VMFZrZLeezFq5lBflMC6IZEU");
                verifyPostParameters.Add("return_landmark", "0");//0：不返回人脸坐标  1：返回83对坐标  2：返回106对坐标
                verifyPostParameters.Add("return_attributes", "gender,age,smiling,headpose,facequality,blur,emotion,ethnicity,beauty,skinstatus");
                //verifyPostParameters.Add("calculate_all", "1");//正式api_key 才能使用此参数,检测图片中所有人脸，并返回数据
                //添加图片参数
                MemoryStream ms = new MemoryStream();
                bitmap.Save(ms, ImageFormat.Jpeg);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                verifyPostParameters.Add("image_base64", Convert.ToBase64String(arr));
                string xx = help.createHttp(url, verifyPostParameters);
                JObject ja = (JObject)JsonConvert.DeserializeObject(xx);
                Thread t = new Thread(() => dataSource(ja));
                t.Start();
            }
            catch (Exception err)
            {
                log.WriteLog(err.ToString());
                return;
            }
        }


        /// <summary>
        /// 数据绑定
        /// </summary>
        /// <param name="ja">数据源</param>
        private void dataSource(JObject ja)
        {
            try
            {
                if (ja.ContainsKey("error_message") || ja["faces"][0] == null)
                {
                    log.WriteLog(ja.GetValue("error_message").ToString());
                    this.labtitle.Text = "人脸识别失败";
                    return;
                }
            }
            catch (Exception err)
            {
                log.WriteLog(err.ToString());
                this.labtitle.Text = "人脸识别失败";
                return;
            }

            y = Convert.ToInt32(ja["faces"][0]["face_rectangle"]["top"]);
            x = Convert.ToInt32(ja["faces"][0]["face_rectangle"]["left"]);
            width = Convert.ToInt32(ja["faces"][0]["face_rectangle"]["width"]);
            height = Convert.ToInt32(ja["faces"][0]["face_rectangle"]["height"]);
            //情绪
            double[] emotion_arr = new double[7];
            emotion_arr.SetValue(Convert.ToSingle(ja["faces"][0]["attributes"]["emotion"]["sadness"]), 0);//sadness：伤心
            emotion_arr.SetValue(Convert.ToSingle(ja["faces"][0]["attributes"]["emotion"]["neutral"]), 1);
            emotion_arr.SetValue(Convert.ToSingle(ja["faces"][0]["attributes"]["emotion"]["disgust"]), 2);
            emotion_arr.SetValue(Convert.ToSingle(ja["faces"][0]["attributes"]["emotion"]["anger"]), 3);
            emotion_arr.SetValue(Convert.ToSingle(ja["faces"][0]["attributes"]["emotion"]["surprise"]), 4);
            emotion_arr.SetValue(Convert.ToSingle(ja["faces"][0]["attributes"]["emotion"]["fear"]), 5);
            emotion_arr.SetValue(Convert.ToSingle(ja["faces"][0]["attributes"]["emotion"]["happiness"]), 6);
            ArrayList list = new ArrayList(emotion_arr);
            list.Sort();
            float max = Convert.ToSingle(list[list.Count - 1]);
            int index = Array.IndexOf(emotion_arr, max);
            switch (index)
            {
                case 0://sadness：伤心
                    help.faceFeature(aq_qingxu_lab, lab_qx_left_bottom, lab_qx_left, lab_qx_right, "愁眉苦脸", "垂头丧气", "悲痛欲绝", Convert.ToInt32(emotion_arr[index]));
                    this.aq_qingxu.Value = (float)emotion_arr[index] * 4;
                    break;
                case 1://平静
                    help.faceFeature(aq_qingxu_lab, lab_qx_left_bottom, lab_qx_left, lab_qx_right, "波澜不惊", "心平气和", "心如止水", Convert.ToInt32(emotion_arr[index]));
                    this.aq_qingxu.Value = (float)emotion_arr[index] * 4;
                    break;
                case 2://disgust：厌恶
                    help.faceFeature(aq_qingxu_lab, lab_qx_left_bottom, lab_qx_left, lab_qx_right, "不屑一顾", "恨之入骨", "深恶痛绝", Convert.ToInt32(emotion_arr[index]));
                    this.aq_qingxu.Value = (float)emotion_arr[index] * 4;
                    break;
                case 3://anger：愤怒
                    help.faceFeature(aq_qingxu_lab, lab_qx_left_bottom, lab_qx_left, lab_qx_right, "怒气冲冲", "怒火中烧", "火冒三丈", Convert.ToInt32(emotion_arr[index]));
                    this.aq_qingxu.Value = (float)emotion_arr[index] * 4;
                    break;
                case 4://surprise：惊讶
                    help.faceFeature(aq_qingxu_lab, lab_qx_left_bottom, lab_qx_left, lab_qx_right, "目瞪口呆", "大吃一惊", "大惊失色", Convert.ToInt32(emotion_arr[index]));
                    this.aq_qingxu.Value = (float)emotion_arr[index] * 4;
                    break;
                case 5://fear：恐惧
                    help.faceFeature(aq_qingxu_lab, lab_qx_left_bottom, lab_qx_left, lab_qx_right, "惶恐不安", "胆战心惊", "惊恐万分", Convert.ToInt32(emotion_arr[index]));
                    this.aq_qingxu.Value = (float)emotion_arr[index] * 4;
                    break;
                case 6://happiness：高兴
                    help.faceFeature(aq_qingxu_lab, lab_qx_left_bottom, lab_qx_left, lab_qx_right, "眉开眼笑", "欢天喜地", "欣喜若狂", Convert.ToInt32(emotion_arr[index]));
                    this.aq_qingxu.Value = (float)emotion_arr[index] * 4;
                    break;
                default:
                    break;
            }

            //性别,年龄，颜值，最高颜值，男或女的背景图片
            if (ja["faces"][0]["attributes"]["gender"]["value"].ToString() == "Male")
            {
                this.lab_xingbie.Text = "绝世美男";
                this.lab_nianling.Text = ja["faces"][0]["attributes"]["age"]["value"].ToString() + "岁";
                if (this.lab_yanzhi.Text != "")
                {
                    if (Convert.ToInt32(this.lab_yanzhi.Text.Substring(0, 2)) > Convert.ToInt32(ja["faces"][0]["attributes"]["beauty"]["male_score"]))
                    {
                        this.lab_zuigaoyanzhi.Text = this.lab_yanzhi.Text;
                    }
                    else
                    {
                        this.lab_zuigaoyanzhi.Text = Convert.ToInt32(ja["faces"][0]["attributes"]["beauty"]["male_score"]).ToString() + "分";
                    }
                }
                else
                {
                    this.lab_zuigaoyanzhi.Text = Convert.ToInt32(ja["faces"][0]["attributes"]["beauty"]["male_score"]).ToString() + "分";
                }

                this.lab_yanzhi.Text = Convert.ToInt32(ja["faces"][0]["attributes"]["beauty"]["male_score"]).ToString() + "分";//颜值
                this.panel_sex.BackgroundImage = Image.FromFile(temppath + "\\Resources\\sex_man.png");
            }
            else
            {
                this.lab_xingbie.Text = "绝世美女";
                this.lab_nianling.Text = ja["faces"][0]["attributes"]["age"]["value"].ToString() + "岁";
                if (this.lab_yanzhi.Text != "")
                {
                    if (Convert.ToInt32(this.lab_yanzhi.Text.Substring(0, 2)) > Convert.ToInt32(ja["faces"][0]["attributes"]["beauty"]["female_score"]))
                    {
                        this.lab_zuigaoyanzhi.Text = this.lab_yanzhi.Text;
                    }
                    else
                    {
                        this.lab_zuigaoyanzhi.Text = Convert.ToInt32(ja["faces"][0]["attributes"]["beauty"]["female_score"]).ToString() + "分";
                    }
                }
                else
                {
                    this.lab_zuigaoyanzhi.Text = Convert.ToInt32(ja["faces"][0]["attributes"]["beauty"]["male_score"]).ToString() + "分";
                }
                this.lab_yanzhi.Text = Convert.ToInt32(ja["faces"][0]["attributes"]["beauty"]["male_score"]).ToString() + "分";//颜值
                this.panel_sex.BackgroundImage = Image.FromFile(temppath + "\\Resources/sex_woman.png");
            }

            //面部特征
            int health = (int)Convert.ToInt32(ja["faces"][0]["attributes"]["skinstatus"]["health"]) / 10;
            int stain = (int)Convert.ToInt32(ja["faces"][0]["attributes"]["skinstatus"]["stain"]) / 10;//色斑
            int acne = (int)Convert.ToInt32(ja["faces"][0]["attributes"]["skinstatus"]["acne"]) / 10;//青春痘
            int dark_circle = (int)Convert.ToInt32(ja["faces"][0]["attributes"]["skinstatus"]["dark_circle"]) / 10;//黑眼圈
            debugFrm.outPutDebug(string.Format("健康:{0:f} ", health));
            debugFrm.outPutDebug(string.Format("色斑:{0:f} ", stain));
            debugFrm.outPutDebug(string.Format("青春痘:{0:f} ", acne));
            debugFrm.outPutDebug(string.Format("黑眼圈:{0:f} ", dark_circle));
            for (int i = 0; i < 9; i++)
            {
                //System.Threading.Thread.Sleep(50);
                if (i < health)
                {
                    picture[i].ImageLocation = temppath + "\\Resources\\555551.png";
                }
                else
                {
                    picture[i].ImageLocation = temppath + "\\Resources\\77771.png";
                }
            }
            for (int i = 10; i < 20; i++)
            {
                //System.Threading.Thread.Sleep(50);
                if (i < stain + 10)
                {
                    picture[i].ImageLocation = temppath + "\\Resources\\666661.png";
                }
                else
                {
                    picture[i].ImageLocation = temppath + "\\Resources\\77771.png";
                }
            }
            for (int i = 20; i < 30; i++)
            {
                //System.Threading.Thread.Sleep(50);
                if (i < acne + 20)
                {
                    picture[i].ImageLocation = temppath + "\\Resources\\666661.png";
                }
                else
                {
                    picture[i].ImageLocation = temppath + "\\Resources\\77771.png";
                }
            }
            for (int i = 30; i < 40; i++)
            {
                //System.Threading.Thread.Sleep(50);
                if (i < dark_circle + 30)
                {
                    picture[i].ImageLocation = temppath + "\\Resources\\666661.png";
                }
                else
                {
                    picture[i].ImageLocation = temppath + "\\Resources\\77771.png";
                }
            }

            //满意度
            int smile = (int)Convert.ToInt32(ja["faces"][0]["attributes"]["smile"]["value"]) / 4;
            int threshold = (int)Convert.ToInt32(ja["faces"][0]["attributes"]["smile"]["threshold"]) / 4;//笑容阈值，value超过此数值，认为有笑容
            debugFrm.outPutDebug(string.Format("满意度:{0:f} ", smile));
            debugFrm.outPutDebug(string.Format("满意度阈值:{0:f}\r\n ", threshold));

            if (tempi <= 1)
            {
                for (int i = 40; i <= 64; i++)
                {
                    System.Threading.Thread.Sleep(50);
                    if (i < smile + 40)
                    {
                        picture[i].ImageLocation = temppath + "\\Resources\\22.png";
                        tempi = i;
                    }
                    else
                    {
                        picture[i].ImageLocation = temppath + "\\Resources\\23.png";
                    }
                }
            }
            else
            {
                if (tempi < smile + 40)//本次红块比上次红块多,增长满意度
                {
                    for (int i = tempi; i <= 64; i++)
                    {
                        System.Threading.Thread.Sleep(50);
                        picture[i].ImageLocation = temppath + "\\Resources\\22.png";
                        tempj = i;
                    }
                }
                else
                {
                    if (tempi >= 64)
                    {
                        //降低满意度
                        for (int i = 64; i >= smile + 40; i--)
                        {
                            System.Threading.Thread.Sleep(50);
                            picture[i].ImageLocation = temppath + "\\Resources\\23.png";
                            tempj = i;
                        }
                    }
                    else
                    {
                        //降低满意度
                        for (int i = tempi; i >= smile + 40; i--)
                        {
                            System.Threading.Thread.Sleep(50);
                            picture[i].ImageLocation = temppath + "\\Resources\\23.png";
                            tempj = i;
                        }
                    }
                }
                tempi = tempj;
            }
            #region  原满意度变化方式
            /*
            if (smile - threshold > 0)
            {
                for (int i = 40; i < 65; i++)
                {
                    System.Threading.Thread.Sleep(50);
                    if (i < smile + 40)
                    {
                        picture[i].ImageLocation = temppath + "\\Resources\\22.png";
                    }
                    else
                    {
                        picture[i].ImageLocation = temppath + "\\Resources\\23.png";
                    }
                }
                //setManyidu(smile);
            }
            else
            {
                for (int i = 64; i >=40; i--)
                {
                    System.Threading.Thread.Sleep(50);
                    if (i > smile + 40)
                    {
                        picture[i].ImageLocation = temppath + "\\Resources\\23.png";
                    }
                    else
                    {
                        picture[i].ImageLocation = temppath + "\\Resources\\22.png";
                    }
                }
                //setManyidu(10);
            }
            tempi = tempj;
            */
            #endregion
        }
        #endregion

        #region 窗体关闭事件
        private void FrmFaceEmotion_FormClosing(object sender, FormClosingEventArgs e)
        {
            //退出所有子线程
            Application.ExitThread();
            Environment.Exit(0);
        }
        #endregion
    }
}
